package com.sntk.registermanager.staff.query;

import com.sntk.registermanager.common.infrastructure.resp.OperatorInfo;
import com.sntk.registermanager.common.infrastructure.resp.PageData;
import com.sntk.registermanager.staff.application.dto.DoctorInfoDTO;
import com.sntk.registermanager.staff.infrastructure.db.entity.DoctorInfoEntity;
import com.sntk.registermanager.staff.infrastructure.db.repository.DoctorInfoDBRepository;
import com.sntk.registermanager.staff.query.mapper.DoctorInfoMapper;
import com.sntk.registermanager.staff.query.params.DoctorCondition;
import com.sntk.registermanager.staff.query.vo.DoctorInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author liuyunxia
 */
@Service
@Transactional(readOnly = true)
public class DoctorInfoQuery {

    @Autowired
    private DoctorInfoMapper doctorInfoMapper;
    @Autowired
    private DoctorInfoDBRepository doctorInfoDBRepository;

    /**
     * 分页查询医生信息
     * @param condition
     * @param operatorInfo
     * @return
     */
    public PageData<DoctorInfoVO> searchDoctorOfCondition(DoctorCondition condition, OperatorInfo operatorInfo){
        Specification<DoctorInfoEntity> specification = new Specification<DoctorInfoEntity>() {
            @Override
            public Predicate toPredicate(Root<DoctorInfoEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if(!StringUtils.isEmpty(condition.getDoctorCondition())){
                    Predicate predicate = criteriaBuilder.equal(root.get("doctorCode"), condition.getDoctorCondition());
                    Predicate predicate1 = criteriaBuilder.like(root.get("doctorName"), "%"+condition.getDoctorCondition()+"%");
                    predicateList.add(criteriaBuilder.or(predicate, predicate1));
                }

                //删除标记
                Predicate predicate = criteriaBuilder.isFalse(root.get("del"));
                predicateList.add(predicate);

                Predicate[] predicates = new Predicate[predicateList.size()];
                return criteriaBuilder.and(predicateList.toArray(predicates));
            }
        };

        //2.分页
        Pageable pageable = PageRequest.of(condition.getCurrPageNo()-1, condition.getLimit(), Sort.by(Sort.Order.asc("doctorName")));
        Page<DoctorInfoEntity> page = doctorInfoDBRepository.findAll(specification,pageable);

        if(page.isEmpty()){
            return new PageData<>(0L, condition.getCurrPageNo(), null);
        }
        List<DoctorInfoVO> doctorInfoVOS = page.stream().map(entry -> doctorInfoMapper.transformToVO(entry)).collect(Collectors.toList());
        return new PageData<>(page.getTotalElements(), condition.getCurrPageNo(), doctorInfoVOS);
    }


    /**
     * 查询所有有效的医生
     * @return
     */
    public List<DoctorInfoDTO> searchAllDoctor(){

        List<DoctorInfoEntity> entities = doctorInfoDBRepository.findAllByDelFalseAndDisabledFalse();
        if(CollectionUtils.isEmpty(entities)){
            return null;
        }
        return entities.stream().map(entity -> doctorInfoMapper.transformToDTO(entity)).collect(Collectors.toList());
    }


    public DoctorInfoDTO searchDoctor(String doctorCode){
        DoctorInfoEntity doctorInfoEntity = doctorInfoDBRepository.findFirstByDoctorCodeAndDelFalse(doctorCode);
        if(doctorInfoEntity == null){
            return null;
        }
        return doctorInfoMapper.transformToDTO(doctorInfoEntity);
    }


}
